﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace GersonFrame.Tool
{
    public static class MathTool
    {
        public static T GetRandomValueFrom<T>(params T[] valuses)
        {
            int index = Random.Range(0, valuses.Length);
            return valuses[index];
        }

        /// <summary>
        /// 获取格式化数据
        /// </summary>
        /// <param name="formatvalue"></param>
        /// <returns></returns>
        public static string GetFormartValue(float formatvalue, int showcount = 4)
        {
            if (formatvalue >= 10000)
            {
                return (int)((formatvalue * 1f / 1000) * Mathf.Pow(10, showcount - (formatvalue / 1000).ToString().Length)) / Mathf.Pow(10, showcount - (formatvalue / 1000).ToString().Length) + "K";
            }
            else return Mathf.FloorToInt(formatvalue).ToString();
        }

        /// <summary>
        /// 获取XZ轴距离
        /// </summary>
        /// <returns></returns>
        public static float GetXZDistance(Vector3 pos1, Vector3 pos2)
        {
            float disx = pos1.x - pos2.x;
            float disz = pos1.z - pos2.z;
            float dis = Mathf.Sqrt(disx * disx + disz * disz);
            return dis;
        }

        /// <summary>
        /// 获取UUiD
        /// </summary>
        /// <returns></returns>
        public static string GenUUID()
        {
            string uuid = System.Guid.NewGuid().ToString("X");
            /*    System.Guid.NewGuid().ToString(); 9af7f46a-ea52-4aa3-b8c3-9fd484c2af12
               string uuidN = System.Guid.NewGuid().ToString("N"); // e0a953c3ee6040eaa9fae2b667060e09 
                      string uuidD = System.Guid.NewGuid().ToString("D"); // 9af7f46a-ea52-4aa3-b8c3-9fd484c2af12
                      string uuidB = System.Guid.NewGuid().ToString("B"); // {734fd453-a4f8-4c5d-9c98-3fe2d7079760}
                      string uuidP = System.Guid.NewGuid().ToString("P"); //  (ade24d16-db0f-40af-8794-1e08e2040df3)
                      string uuidX = System.Guid.NewGuid().ToString("X"); // {0x3fa412e3,0x8356,0x428f,{0xaa,0x34,0xb7,0x40,0xda,0xaf,0x45,0x6f}}*/
            return uuid;
        }


        /// <summary>
        /// 时间戳(秒)
        /// </summary>
        public static long TimeStamp
        {
            get {

                System.DateTime startTime = System.TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
                long timeStamp = (System.DateTime.Now - startTime).Ticks / 10000;
                return timeStamp;
            }
        }

        /// <summary>
        /// 获取反射向量
        /// </summary>
        public static Vector3 GetReflectDir(Vector3 orildir,Vector3 planeDir)
        {
            Vector3 normal = GetNormalDir(planeDir);
            Vector3 reflectdir = Vector3.Reflect(orildir,normal);
            return reflectdir;
        }

        /// <summary>
        /// 获取向量的法向量
        /// </summary>
        /// <param name="vector"></param>
        /// <returns></returns>
        public static Vector3 GetNormalDir(Vector3 vector)
        {
            if (vector.z == 0)
                return new Vector3(0, 0, 1);
            else
                return new Vector3(-vector.z / vector.x, 0, 1).normalized;
        }


        /// <summary>
        /// 围绕某点旋转指定角度
        /// </summary>
        /// <param name="position">自身坐标</param>
        /// <param name="center">旋转中心</param>
        /// <param name="axis">围绕旋转轴</param>
        /// <param name="angle">旋转角度</param>
        /// <returns></returns>
        public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
        {
            return Quaternion.AngleAxis(angle, axis) * (position - center) + center;
        }
        public static Quaternion CalQuaternion(Vector3 dir)
        {
            Quaternion cal = new Quaternion();
            Vector3 euler = Quaternion.LookRotation(dir).eulerAngles;

            //欧拉角Y: cosY = z/sqrt(x^2+z^2)
            float CosY = dir.z / Mathf.Sqrt(dir.x * dir.x + dir.z * dir.z);
            float CosYDiv2 = Mathf.Sqrt((CosY + 1) / 2);
            if (dir.x < 0) CosYDiv2 = -CosYDiv2;

            float SinYDiv2 = Mathf.Sqrt((1 - CosY) / 2);

            //欧拉角X: cosX = sqrt((x^2+z^2)/(x^2+y^2+z^2)
            float CosX = Mathf.Sqrt((dir.x * dir.x + dir.z * dir.z) / (dir.x * dir.x + dir.y * dir.y + dir.z * dir.z));
            if (dir.z < 0) CosX = -CosX;
            float CosXDiv2 = Mathf.Sqrt((CosX + 1) / 2);
            if (dir.y > 0) CosXDiv2 = -CosXDiv2;
            float SinXDiv2 = Mathf.Sqrt((1 - CosX) / 2);

            //四元数w = cos(x/2)cos(y/2)
            cal.w = CosXDiv2 * CosYDiv2;
            //四元数x = sin(x/2)cos(y/2)
            cal.x = SinXDiv2 * CosYDiv2;
            //四元数y = cos(x/2)sin(y/2)
            cal.y = CosXDiv2 * SinYDiv2;
            //四元数z = sin(x/2)sin(y/2)
            cal.z = -SinXDiv2 * SinYDiv2;


            return cal;
        }


        /// <summary>
        /// 获取随机不重复数量 左闭右开
        /// </summary>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <param name="getcount"></param>
        /// <returns></returns>
        public static List<int> GetRandomValueNoRepeat(int min,int max,int getcount)
        {
            List<int> values = new List<int>();
            List<int> returnvalues = new List<int>();
            for (int i = min; i <max; i++)
            {
                values.Add(i);
            }

            for (int i = 0; i < getcount; i++)
            {
                if (values.Count <= 0)
                {
                    MyDebuger.LogError("随机数量不足 ");
                    break;
                }   
                int valueindex = Random.Range(0, values.Count);
                returnvalues.Add(values[valueindex]);
                values.RemoveAt(valueindex);
            }
            return returnvalues;
        }


        /// <summary>
        /// 获取圆上的点
        /// </summary>
        /// <param name="oril"></param>
        /// <param name="raudio"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static Vector3[] GetCyclePoses(Vector3 oril, float raudio, int count, bool worldforward = true)
        {
   
            if (count<=0)
            {
                Debug.LogError("GetCyclePoses count less 0");
                return new Vector3[0];
            }
            Vector3[] poss = new Vector3[count];
            float angleRad = Mathf.Deg2Rad * 360;
            float angleCur = angleRad;
            float angledelta = angleRad / count;

            for (int i = 0; i < count; i++)
            {
                float cosA = Mathf.Cos(angleCur);
                float sinA = Mathf.Sin(angleCur);

                if (worldforward)
                    poss[i] = oril + new Vector3(raudio * sinA, 0, raudio * cosA);
                else
                    poss[i] = oril + new Vector3(-raudio * sinA, 0, -raudio * cosA);
           
                angleCur -= angledelta;
            }
            return poss;
        }



        /// <summary>
        /// 计算射线和面的交点 
        /// 会有一定误差 ， 浮点数计算没有办法
        /// </summary>
        /// <param name="ray">射线</param>
        /// <param name="normal">面的法线</param>
        /// <param name="Point">面上的一点</param>
        /// <param name="ret">交点</param>
        /// <returns>线和面是否相交</returns>
      public static  bool IntersectionOfRayAndFace(Ray ray, Vector3 normal, Vector3 Point, out Vector3 ret)
        {
            float dirvalue = Vector3.Dot(ray.direction, normal);
            if (dirvalue >=0)
            {
                //如果平面法线和射线垂直 则不会相交
                ret = Vector3.zero;
                return false;
            }
            Vector3 Forward = normal;
            Vector3 Offset = Point - ray.origin; //获取线的方向
            float DistanceZ = Vector3.Angle(Forward, Offset); //计算夹角
            DistanceZ = Mathf.Cos(DistanceZ / 180f * Mathf.PI) * Offset.magnitude; //算点到面的距离
            DistanceZ /= Mathf.Cos(Vector3.Angle(ray.direction, Forward) / 180f * Mathf.PI); //算点沿射线到面的距离
            ret = ray.origin + ray.direction * DistanceZ; //算得射线和面的交点
            return true;
        }


    }
}

